﻿using System.Threading;
using HCore;
using MEat;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Logger = HCore.Logger;

public class GameController : MonoBehaviour
{
    private const int FrameRate = GameDefine.FRAME_RATE;

    public int serverPort = 0;
    public int playerNum = 1;

    public string playerName = "";
    public string connectIp = "";
    public int connectPort = 0;

    public bool recordMode = false;
    public string recordDataPath = "";

    private float _timeScale = 1;

    private Thread _serverThread;

    public float timeScale
    {
        get { return _timeScale; }
        set
        {
            _timeScale = value;
            _hGame.timer.SetTimerScale((FixConst) _timeScale);
        }
    }

    private HGame _hGame;

    void Start()
    {
#if DEVELOPMENT_BUILD
#if UNITY_IOS || UNITY_IPHONE || UNITY_ANDROID
        gameObject.AddComponent<LunarConsolePlugin.LunarConsole>();
#endif
#endif

        Logger.Set(Debug.Log, Debug.LogWarning, Debug.LogError);
        DisplayObjectFactory.SetDisplayCreator(EntityType.Dummy, typeof(DummyDisplay));
        DisplayObjectFactory.SetDisplayCreator(EntityType.Pendulum, typeof(PendulumDisplay));
        DisplayObjectFactory.SetDisplayCreator(EntityType.Spring, typeof(SpringDisplay));
        CommandFactory.SetDisplayCreator(GameDefine.EMPTY_COMMAND, typeof(EmptyCommand));
        CommandFactory.SetDisplayCreator(CommandType.Move, typeof(MoveCommand));

        LaunchParams launchParams = new LaunchParams(FrameRate);
        launchParams.connectIp = connectIp;
        launchParams.connectPort = connectPort;
        launchParams.playerName = playerName;

        if (recordMode && !string.IsNullOrEmpty(recordDataPath))
        {
            InputMemoryBitStream input = FileUtility.Open(recordDataPath);
            if (input != null)
                launchParams.recordData = new RecordData(input);
        }
        else if (serverPort > 0)
        {
            _serverThread = new Thread(LaunchServer);
            _serverThread.Start();
        }


        _hGame = new MEatGame(launchParams);
        _hGame.timer.SetTimerScale((FixConst) timeScale);
    }

    // Update is called once per frame
    void Update()
    {
        // 输入
        UpdateInput();

        _hGame.Update();
    }

    public void UpdateInput()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (!Physics.Raycast(ray, out var hit))
            {
                return;
            }

            MoveCommand moveCommand = new MoveCommand();
            moveCommand.playerId = _hGame.playerId;
            moveCommand.networkId = _hGame.playerId;
            moveCommand.SetTarget(hit.point.ToHVec3());
            _hGame.commandMgr.AddUserCommand(moveCommand);
        }
        else if (Input.touchCount > 0)
        {
            var touch = Input.GetTouch(0);
            Ray ray = Camera.main.ScreenPointToRay(touch.position);
            if (!Physics.Raycast(ray, out var hit))
            {
                return;
            }

            MoveCommand moveCommand = new MoveCommand();
            moveCommand.playerId = _hGame.playerId;
            moveCommand.networkId = _hGame.playerId;
            moveCommand.SetTarget(hit.point.ToHVec3());
            _hGame.commandMgr.AddUserCommand(moveCommand);
        }
    }

    public void OnDestroy()
    {
        if (!recordMode && !string.IsNullOrEmpty(recordDataPath))
            _hGame.SaveRecord(recordDataPath);

        _hGame.Dispose();
        if (_serverThread != null)
        {
            _serverThread.Interrupt();
            _serverThread.Abort();
        }
    }

    private void LaunchServer()
    {
        Server server = new Server(serverPort, playerNum, FrameRate);
        while (true)
        {
            server.Update();
        }
    }
}